/***************************************************************************
 *   Copyright (C) 2008 by Ivan Blagoev Topolsky   *
 *   ivan.topolsky@genebio.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 3 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef XENO_FREUDANALYST_H
#define XENO_FREUDANALYST_H

#include <iostream>
#include <string>
#include <set>
#include <map>

// Captain-bol
#include <runlcmsms.h>
// Xeno-bol
#include "xeno.h"

// OLE/COM support
#include "disphelper.h"





namespace xeno {
namespace freud {

	using namespace std;	// STL
	using namespace bol;	// Captain bol

/**
	This class is used to package together the different phases in reading a Analyst's Wiff files
	together with the object that are passed around.

	It doesn't actually need to be an object, it's just better packaged like this.

	@author Ivan Blagoev Topolsky <ivan.topolsky@genebio.com>
 */
class analyst{
public:
	// data
	RunLcmsms *run; // Run that we are building

	// informations
	int numsam;	int cursam;
	int numpe;	int curpe;
	int numxp;	int curxp;
	int numcy;	int curcy;

	// parameters
	bool docentroid;	// set to true if centroidation must be applied on data
	// FIXME program crashes while trying to centroid	

private:
	// data that gets passed around between steps
	// for some reason, Analyst doesn't work well with CDispPtr;
	IDispatch *wiff;
	IDispatch *chrom;
	IDispatch *spec;
	vector<string> samnames;

	typedef set<unsigned long> CYCLEMAP;
	typedef map<unsigned long,CYCLEMAP *> EXPMAP;
	typedef map<unsigned long,EXPMAP *> PERIODMAP;

	PERIODMAP *RefMap;

public:
	analyst() : wiff(NULL), chrom(NULL), spec(NULL), run(NULL), docentroid(false), 
		numsam(0), numpe(0), numxp(0),
		cursam(0), curpe(0), curxp(0),
		RefMap(NULL) {
	}

	~analyst() {
		// free the
		if (wiff) SAFE_RELEASE(wiff);
		if (chrom) SAFE_RELEASE(chrom);
		if (spec) SAFE_RELEASE(spec);
	}


	RunLcmsms *getRun() const { return run; }
	RunLcmsms *setRun(RunLcmsms *ptr) { return run = ptr; }

	/**
	 * num/current :
	 * the following collection of functions is useful to have a status of the current process
	 */
	int numsamples() const { return numsam; }
	int currentsample() const { return cursam; }
	const string& samplename(int sample = 0) const { return samnames[0];}
	int numperiods() const { return numpe; }
	int currentperiod() const { return curpe; }
	int numexps() const { return numxp; }
	int currentexp() const { return curxp; }
	int numcylces() const { return numcy; }
	int currentcylce() const { return curcy; }

	long long mkrefid() const;


	/**
	 * decoding steps :
	 */
	void initfile(const char *ifname);
	void samplelist();
	void dosample(const int sample, RunLcmsms *ptr = NULL, const bool skipms1 = false, const bool skipms2 = false, const bool dropms1 = false, const bool dropms2 = false, ExtractList *reflist = NULL);
	
	typedef void (analyst::*EFFECTOR_FUNC_PTR) (const int sam, const int pe, const int xp, const float retensiontime, const double tic, const bool skip, bool docentroid);

	void dospectra(const EFFECTOR_FUNC_PTR effector, const int sam, const int pe, const int xp, const bool skip = false, bool docentroid = false);

	void do_single_spectrum_mrm(const int sam, const int pe, const int xp, const float retentiontime, const double tic = 0., const bool skip = false, bool docentroid = false);
	void do_single_spectrum_ms1(const int sam, const int pe, const int xp, const float  retentiontime, const double tic = 0., const bool skip = false, bool docentroid = false);
	void do_single_spectrum_ms2(const int sam, const int pe, const int xp, const float  retentiontime, const double tic = 0., const bool skip = false, bool docentroid = false);

	void getdata(Spectrum< PeakIntensity* > *sp, int num);
	void buildptr();

	void initextract_map(ExtractList *ptr);
	bool checkmap(int pe, int xp);
	bool checkmap(int pe, int xp, int cy);
};


}
}

#endif
